(function () {
	var ns = ij.pkg('core').namespaceString;
	
	ij.core.Renderer = ij.core.Observable.extend({
		init: function (config) {
			return this._super(ij.apply({
				classname: ns + '.Renderer',
				displayObject: null,
				x: null,
				y: null,
				z: null,
				angle: null,
				width: null,
				height: null,
				transformOrigin: {
					dx: null,
					dy: null,
					dz: null
				},
				sprite: {
					color: null,
					url: null,
					x: null,
					y: null,
					repeat: null
				}
			}, config));
		},
		setDisplayObject: function (displayObject) {
			if (displayObject instanceof ij.core.DisplayObject) {
				this.displayObject = displayObject;
			}
		},
		setTransformOrigin: function () {
			this.transformOrigin = this.displayObject.transformOrigin;
			
			return this;
		},
		setSprite: function () {
			this.sprite = this.displayObject.sprite;
			
			return this;
		},
		render: function () {},
		isRendered: function () {},
		isVisible: function () {}
	});
	
	ij.core.DomRenderer = ij.core.Renderer.extend({
		init: function (config) {
			return this._super(ij.apply({
				classname: ns + '.DomRenderer',
				dom: null,
				attrs: [],
				visible: true,
				_transformationCSSRules: ['-webkit-transform', '-moz-transform', '-o-transform', '-ms-transform', 'transform'],
				_transformOriginCSSRules: ['-webkit-transform-origin', '-moz-transform-origin', '-o-transform-origin', '-ms-transform-origin', 'transform-origin']
			}, config));
		},
		render: function () {
			if (this.displayObject) {
				if (!this.isRendered() && this.displayObject.parent.renderer instanceof ij.core.DomRenderer) {
					this.attach(this.displayObject.parent.renderer.dom);
				}
				
				this.setSprite().setTransformOrigin().setTransformation();
			}
			return this;
		},
		attach: function (dom) {
			if (this.isRendered()) {
				this.detach();
			}
			
			this.dom = $('<div class="'+this.displayObject.classes.join(' ')+'" '+(ij.map(this.attrs, function (i, item) {
				return i + '="'+item+'"';
			}, this)).join(' ')+'/>').appendTo(dom);
			this.dom.data('ij-object', this);
			this.setTransformation();
			this.dispatchEvent(new ij.core.Event({
				name: 'attach',
				data: {
					'target': dom
				}
			}));
			
			return this;
		},
		detach: function () {
			if (this.isRendered()) {
				this.dom.remove();
				this.dom = null;
				this.dispatchEvent(new ij.core.Event({
					name: 'detach'
				}));
			}
		},
		isRendered: function () {
			return !!this.dom;
		},
		isVisible: function () {
			return this.visible;
		},
		setTransformation: function () {
			if (this.x !== this.displayObject.getX() || 
					this.y !== this.displayObject.getY() ||
					this.z !== this.displayObject.getZ() ||
					this.angle !== this.displayObject.getAngle()) {
				this.x = this.displayObject.getX();
				this.y = this.displayObject.getY();
				this.z = this.displayObject.getZ();
				this.angle = this.displayObject.getAngle();
				
				var _transformationString = 'translate3d('+this.x+'px '+this.y+'px '+this.z+'px) rotate('+this.angle+'deg)';
				if (this.isRendered()) {
					this.dom.css(ij.mapObject(this._transformationCSSRules, function(i, item){
						var res = {};
						res[item] = _transformationString;
						return res;
					}, this));
				}
			}
			return this;
		},
		setTransformOrigin: function () {
			var tOrig = this.displayObject.getTransformOrigin();
			if (this.transformOrigin.dx !== tOrig.dx || 
					this.transformOrigin.dy !== tOrig.dy ||
					this.transformOrigin.dz !== tOrig.dz) {
				ij.apply(this.transformOrigin, this.displayObject.transformOrigin);
				var _transformOriginString = (this.x + this.transformOrigin.dx)+'px '+(this.y + this.transformOrigin.dy)+'px';
				if (this.isRendered()) {
					this.dom.css(ij.mapObject(this._transformOriginCSSRules, function(i, item){
						var res = {};
						res[item] = _transformOriginString;
						return res;
					}, this));
				}
			}
			
			return this;
		},
		setSprite: function () {
			var sprite = this.displayObject.getSprite();
			
			if (this.sprite.color !== sprite.color || 
					this.sprite.x !== sprite.x ||
					this.sprite.y !== sprite.y ||
					this.sprite.repeat !== sprite.repeat) {
				ij.apply(this.sprite, sprite);
				
				if (this.isRendered()) {
					this.dom.css({
						background: this.sprite.color + (this.sprite.url?' url("'+this.sprite.url+'") ':' ') + (-this.sprite.x) + 'px ' + (-this.sprite.y) + 'px ' + this.sprite.repeat
					});
				}
			}
			
			return this;
		}
	});
	
	ij.core.ContainerDomRenderer = ij.core.DomRenderer.extend({
		init: function (config) {
			return this._super(ij.apply({
				classname: ns + '.ContainerDomRenderer'
			}, config));
		},
		render: function () {
			this._super();
			
			if (this.displayObject) {
				this.displayObject.objects.each(function (i, item) {
					item.render();
				}, this);
			}
			return this;
		},
		attach: function (dom) {
			this._super(dom);
			console.log(this.displayObject.classname, this.dom);
			if (this.displayObject) {
				this.displayObject.objects.each(function (i, item) {
					console.log(item.classname);
					if (item.renderer && item.renderer instanceof ij.core.DomRenderer) {
						console.log('a');
						item.renderer.attach(this.dom);
					}
				}, this);
			}
			
			return this;
		},
		detach: function () {
			if (this.isRendered()) {
				this.dom.remove();
				this.dom = null;
				this.dispatchEvent(new ij.core.Event({
					name: 'detach'
				}));
			}
		}
	});
	
	ij.core.ViewportDomRenderer = ij.core.ContainerDomRenderer.extend({
		init: function (config) {
			return this._super(ij.apply({
				classname: ns + '.ViewportDomRenderer'
			}, config));
		},
		attach: function (dom) {
			this._super(dom);
			dom.addClass('ij-viewport-holder');
			dom.on('webkitTransitionEnd', '.ij-animated-object', function () {
				var obj = $(this).data('ij-object');
				if (obj && obj._webkitTransitionEndHandler) {
					obj._webkitTransitionEndHandler();
				}
			});
			var _this = this;
			$(window).bind('resize.ij-viewport-'+this.uid, function () {
				_this._windowResizeHandler(dom);
			});
			this._windowResizeHandler(dom);
			
			return this;
		},
		detach: function () {
			$(window).unbind('.ij-scene-'+this.uid);
			this._super();
			
			return this;
		},
		_windowResizeHandler: function (dom) {
			this.dom.width(dom.width()).height(dom.height());
			this.dispatchEvent('resize');
		},
		setTransformation: function () {
			return this;
		},
		setTransformOrigin: function () {
			return this;
		},
		setSprite: function () {
			return this;
		}
	});
	
	ij.core.EngineDomRenderer = ij.core.DomRenderer.extend({
		init: function (config) {
			return this._super(ij.apply({
				classname: ns + '.EngineDomRenderer'
			}, config));
		},
		render: function () {
			if (!this.isRendered()) {
				this.attach();
			}
			
			if (this.displayObject) {
				this.displayObject.objects.each(function (i, item) {
					item.render();
				}, this);
			}
			return this;
		},
		attach: function () {
			this.dom = $('body');
			
			if (this.displayObject) {
				this.displayObject.objects.each(function (i, item) {
					if (item.renderer && item.renderer instanceof ij.core.DomRenderer) {
						item.renderer.attach(this.dom);
					}
				}, this);
			}
			
			return this;
		}
	});
})();